﻿ #region Disclaimer/Info
 
 /////////////////////////////////////////////////////////////////////////////////////////////////
 //
 //   File:		WebUtils.cs
 //   Website:		http://dexterblogengine.com/
 //   Authors:		http://dexterblogengine.com/About.ashx
 //   Rev:		1
 //   Created:		19/01/2011
 //   Last edit:		19/01/2011
 //   License:		GNU Library General Public License (LGPL)
 // 
 //   For updated news and information please visit http://dexterblogengine.com/
 //   Dexter is hosted to Codeplex at http://dexterblogengine.codeplex.com
 //   For any question contact info@dexterblogengine.com
 //
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 #endregion

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using System.Xml;
using Dexter.CallContext;
using Dexter.Core;
using Dexter.Logger.Contracts;

namespace Dexter.Web.Utils {
	public class WebUtils : IWebUtils {
		const string COOKIE_NAME = "Dexter_Cookie";
		readonly HttpContextBase contex;
		readonly ILogger logger;

		public WebUtils ( ILogger logger , IDexterContext contex ) {
			this.logger = logger;
			this.contex = contex.Context;
		}

		#region IWebUtils Members

		public string DownloadWebPage ( Uri url ) {
			var request = ( HttpWebRequest ) WebRequest.Create ( url );

			request.Headers[ "Accept-Encoding" ] = "gzip";
			request.Headers[ "Accept-Language" ] = "en-us";
			request.UserAgent = DexterInfo.UserAgent;
			request.Credentials = CredentialCache.DefaultNetworkCredentials;
			request.AutomaticDecompression = DecompressionMethods.GZip;

			using ( WebResponse response = request.GetResponse ( ) ) {
				using ( var reader = new StreamReader ( response.GetResponseStream ( ) ) ) {
					return reader.ReadToEnd ( );
				}
			}
		}

		public void SendTrackBack ( TrackBackMessage message ) {
			if ( message == null ) {
				throw new ArgumentNullException ( "message" );
			}

			var encoding = new ASCIIEncoding ( );
			byte[] data = encoding.GetBytes ( message.ToString ( ) );

			var request = ( HttpWebRequest ) WebRequest.Create ( message.UrlToNotifyTrackback );
			request.UserAgent = DexterInfo.UserAgent;
			request.Credentials = CredentialCache.DefaultNetworkCredentials;
			request.Method = "POST";
			request.ContentLength = data.Length;
			request.ContentType = "application/x-www-form-urlencoded";
			request.KeepAlive = false;
			request.Timeout = 20000;

			using ( Stream myWriter = request.GetRequestStream ( ) ) {
				myWriter.Write ( data , 0 , data.Length );
			}

			HttpWebResponse response;
			try {
				response = ( HttpWebResponse ) request.GetResponse ( );
				string answer;
				using ( var sr = new StreamReader ( response.GetResponseStream ( ) ) ) {
					answer = sr.ReadToEnd ( );
				}

				if ( response.StatusCode == HttpStatusCode.OK && answer.Contains ( "<error>0</error>" ) ) {
					throw new HttpException ( ( int ) response.StatusCode , response.StatusCode.ToString ( ) );
				}
			}
			catch ( Exception exc ) {
				exc.Data.Add ( "Item Title:" , message.Title );
				exc.Data.Add ( "Url To Notify Trackback:" , message.UrlToNotifyTrackback );

				logger.Error ( "Send TrackBack Error" , exc );
			}
		}

		public void SendPingBack ( Uri sourceUrl , Uri targetUrl ) {
			if ( sourceUrl == null || targetUrl == null ) {
				return;
			}

			try {
				HttpWebRequest request = ( HttpWebRequest ) WebRequest.Create ( targetUrl );
				request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10 (.NET CLR 3.5.30729)";
				request.Credentials = CredentialCache.DefaultNetworkCredentials;
				HttpWebResponse response = ( HttpWebResponse ) request.GetResponse ( );
				string pingUrl = ( string.IsNullOrEmpty ( response.Headers[ "x-pingback" ] ) )
				                 	? response.Headers[ "pingback" ]
				                 	: response.Headers[ "x-pingback" ];
				Uri url;
				if ( !string.IsNullOrEmpty ( pingUrl ) && Uri.TryCreate ( pingUrl , UriKind.Absolute , out url ) ) {
					request = ( HttpWebRequest ) WebRequest.Create ( url );
					request.Method = "POST";
					//request.Timeout = 10000;
					request.ContentType = "text/xml";
					request.ProtocolVersion = HttpVersion.Version11;
					request.Headers[ "Accept-Language" ] = "en-us";
					AddXmlToRequest ( sourceUrl , targetUrl , request );
					HttpWebResponse response2 = ( HttpWebResponse ) request.GetResponse ( );
					response2.Close ( );
				}
			}
			catch ( Exception ex ) {
				ex.Data.Add ( "Source Url: " , sourceUrl );
				ex.Data.Add ( "Target Url: " , targetUrl );

				// Stops unhandled exceptions that can cause the app pool to recycle
				logger.Error ( "Send PingBack Error" , ex );
			}
		}

		public string GetCookieValue ( string key ) {
			HttpCookie cookie = contex.Request.Cookies.Get ( COOKIE_NAME );

			if ( cookie != null ) {
				return cookie[key].Decrypt ( "{0x68a04911,0x312b,0x4d3c,{0xac,0x71,0x5d,0x80,0xea,0xae,0x11,0x23}}" );
			}

			return string.Empty;
		}

		public void SetCookieValue ( string key , object value ) {
			HttpCookie cookie = new HttpCookie ( COOKIE_NAME ) {
				HttpOnly = true
			};

			cookie.Expires.AddDays ( 30 );
			cookie.Values.Add ( key, value.ToString ( ).Encrypt ( "{0x68a04911,0x312b,0x4d3c,{0xac,0x71,0x5d,0x80,0xea,0xae,0x11,0x23}}" ) );
		}

		public HttpContextBase Contex {
			get { return contex; }
		}

		#endregion

		static void AddXmlToRequest ( Uri sourceUrl , Uri targetUrl , WebRequest webreqPing ) {
			Stream stream = webreqPing.GetRequestStream ( );
			using ( var writer = new XmlTextWriter ( stream , Encoding.ASCII ) ) {
				writer.WriteStartDocument ( true );
				writer.WriteStartElement ( "methodCall" );
				writer.WriteElementString ( "methodName" , "pingback.ping" );
				writer.WriteStartElement ( "params" );

				writer.WriteStartElement ( "param" );
				writer.WriteStartElement ( "value" );
				writer.WriteElementString ( "string" , sourceUrl.ToString ( ) );
				writer.WriteEndElement ( );
				writer.WriteEndElement ( );

				writer.WriteStartElement ( "param" );
				writer.WriteStartElement ( "value" );
				writer.WriteElementString ( "string" , targetUrl.ToString ( ) );
				writer.WriteEndElement ( );
				writer.WriteEndElement ( );

				writer.WriteEndElement ( );
				writer.WriteEndElement ( );
			}
		}
	}
}
